package com.fit.exercise.msgp2p;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;

public class T2Messenger {

	// Default my info
	public static PersonInfo myInfo = new PersonInfo("ThuanSB", "localhost",
			2211);

	public static boolean isListen = true;

	private JFrame frmPpMessenger;
	private JToolBar toolBar;
	private JSplitPane splitPane;
	private JLabel lbThuanbsf, lbTmessenger;
	private JPanel panel;
	private JPanel panel_1;
	private JButton btnAddNewFriend;
	public static JList<String> list;
	public static DefaultListModel<String> listModel;
	private JScrollPane listScrollPane;
	private JPopupMenu popupMenu;

	// Add friend dialog
	private JDialog addFriendDialog;
	private JPanel dialogPanel;
	private JLabel lbName, lbIPAddress, lbPort;
	private JTextField txtName;
	private JTextField txtIPAddress;
	private JTextField txtPort;
	private JButton saveButton;

	// List friend
	public static List<PersonInfo> friendList;
	private Component glue;
	private JButton btnSetting;

	public static List<ChatFrame> chatFrames = new ArrayList<ChatFrame>();

	public static List<GroupChatFrame> groupChatFrames = new ArrayList<GroupChatFrame>();
	private JButton btnGroupChat;

	// Setting pannel
	// JPanel settingPanel = new JPanel();
	// public static JTextField txtMyPort = new JTextField(myPort.toString());
	// public static JTextField txtMyIP = new JTextField(myIPAddress);

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					T2Messenger window = new T2Messenger();
					window.frmPpMessenger.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public T2Messenger() {
		initialize();
		UDPUtil.listenToReceiveMessage();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		try {
			friendList = Util.readFromFile(Util.filePath);
		} catch (Exception e) {
			System.out.println("Can't read friends list from file");
			e.printStackTrace();
		}
		frmPpMessenger = new JFrame();
		frmPpMessenger.setMaximumSize(new Dimension(80, 700));
		frmPpMessenger.setMinimumSize(new Dimension(80, 500));
		frmPpMessenger.setPreferredSize(new Dimension(80, 500));
		frmPpMessenger.setTitle("P2P Messenger");
		frmPpMessenger.setBounds(100, 100, 450, 300);
		frmPpMessenger.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmPpMessenger.getContentPane().add(getToolBar(), BorderLayout.SOUTH);
		frmPpMessenger.getContentPane().add(getPanel(), BorderLayout.CENTER);

		// settingPanel.add(txtMyPort);
		// settingPanel.add(txtMyIP);
	}

	private JToolBar getToolBar() {
		if (toolBar == null) {
			toolBar = new JToolBar();
			toolBar.add(getSplitPane());
		}
		return toolBar;
	}

	private JSplitPane getSplitPane() {
		if (splitPane == null) {
			splitPane = new JSplitPane();
			splitPane.setLeftComponent(getLblThuanbsf());
			splitPane.setRightComponent(getLblTmessenger());
		}
		return splitPane;
	}

	private JLabel getLblThuanbsf() {
		if (lbThuanbsf == null) {
			lbThuanbsf = new JLabel("ABC");
		}
		return lbThuanbsf;
	}

	private JLabel getLblTmessenger() {
		if (lbTmessenger == null) {
			lbTmessenger = new JLabel("T2Messenger");
		}
		return lbTmessenger;
	}

	private JPanel getPanel() {
		if (panel == null) {
			panel = new JPanel();
			panel.setLayout(new BorderLayout(0, 0));
			panel.add(getPanel_1(), BorderLayout.NORTH);
			panel.add(getListScrollPane(), BorderLayout.CENTER);
		}
		return panel;
	}

	private JPanel getPanel_1() {
		if (panel_1 == null) {
			panel_1 = new JPanel();
			panel_1.setLayout(new BoxLayout(panel_1, BoxLayout.X_AXIS));
			panel_1.add(getBtnGroupChat());
			panel_1.add(getGlue());
			panel_1.add(getBtnSetting());
			panel_1.add(getBtnAddNewFriend());
		}
		return panel_1;
	}

	private JButton getBtnAddNewFriend() {
		if (btnAddNewFriend == null) {
			btnAddNewFriend = new JButton("Add friend");
			btnAddNewFriend.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {

					getAddFriendDialog().setVisible(true);

				}
			});
		}
		return btnAddNewFriend;
	}

	private void updateListModel() {
		if (!listModel.isEmpty())
			listModel.removeAllElements();
		for (PersonInfo f : friendList) {
			listModel.addElement(f.getName() + " - (" + f.getIpAddress() + ":"
					+ f.getPort() + ")");
		}
	}

	private JList<String> getList() {
		if (list == null) {
			list = new JList<>();
			listModel = new DefaultListModel<>();
			updateListModel();
			list.setModel(listModel);

			list.addMouseListener(new MouseAdapter() {

				@Override
				public void mousePressed(MouseEvent e) {
					check(e);
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					check(e);
				}

				private void check(MouseEvent e) {
					if (e.isPopupTrigger()) {
						// select item
						list.setSelectedIndex(list.locationToIndex(e.getPoint()));
						// show popup
						getPopupMenu().show(list, e.getX(), e.getY());
					}
				}

				@Override
				public void mouseClicked(MouseEvent e) {
					if (e.getClickCount() == 2) {

						ChatFrame chatFrame = new ChatFrame();
						chatFrame.setChatFriend(friendList.get(list
								.getSelectedIndex()));

						int idx = T2Messenger.chatFrames.indexOf(chatFrame);
						if (idx < 0) {
							chatFrames.add(chatFrame);
						} else {
							chatFrame = T2Messenger.chatFrames.get(idx);
						}
						chatFrame.setVisible(true);

					}
				}

			});
		}
		return list;
	}

	private JScrollPane getListScrollPane() {
		if (listScrollPane == null) {
			listScrollPane = new JScrollPane(getList());
			listScrollPane.setMaximumSize(new Dimension(100, 32767));
		}
		return listScrollPane;
	}

	public JDialog getAddFriendDialog() {
		if (addFriendDialog == null) {
			addFriendDialog = new JDialog(frmPpMessenger);

			addFriendDialog.setBounds(200, 200, 400, 200);

			lbName = new JLabel("Name");
			lbIPAddress = new JLabel("IP Address");
			lbPort = new JLabel("Port");

			addFriendDialog.getContentPane().add(getDialogPanel(),
					BorderLayout.CENTER);

			dialogPanel.add(lbName);
			dialogPanel.add(getTxtName());

			dialogPanel.add(lbIPAddress);
			dialogPanel.add(getTxtIPAddress());

			dialogPanel.add(lbPort);
			dialogPanel.add(getTxtPort());

			saveButton = new JButton("Save");

			saveButton.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {

					try {
						if (txtName.getText() != null
								&& txtIPAddress.getText() != null
								&& txtPort != null
								&& !txtName.getText().isEmpty()
								&& !txtIPAddress.getText().isEmpty()
								&& !txtPort.getText().isEmpty()) {
							PersonInfo personInfo = new PersonInfo(getTxtName()
									.getText(), getTxtIPAddress().getText(),
									Integer.parseInt(getTxtPort().getText()));

							int resultCheck = Util.checkPersonExist(personInfo,
									friendList);
							if (resultCheck == 1) {
								JOptionPane
										.showMessageDialog(
												frmPpMessenger,
												"This name is exist. Please enter another name",
												"Error",
												JOptionPane.ERROR_MESSAGE);
								return;
							} else if (resultCheck == 2) {
								JOptionPane
										.showMessageDialog(
												frmPpMessenger,
												"This IP Address & Port is exist in your friend list",
												"Error",
												JOptionPane.ERROR_MESSAGE);
								return;
							}

							if (personInfo != null) {
								listModel.addElement(getTxtName().getText());
								Util.saveToFile(Util.filePath, personInfo);
								friendList.add(personInfo);
								addFriendDialog.setVisible(false);
							}
						} else {
							JOptionPane
									.showMessageDialog(
											frmPpMessenger,
											"Can not add friend. Please check the input: All fields are required",
											"Error", JOptionPane.ERROR_MESSAGE);
						}
					} catch (Exception e) {
						JOptionPane
								.showMessageDialog(
										frmPpMessenger,
										"Can not add friend. Please check the input: Port number must be a integer number",
										"Error", JOptionPane.ERROR_MESSAGE);
					}

				}
			});

			dialogPanel.add(new JLabel());
			dialogPanel.add(saveButton);
		}
		return addFriendDialog;
	}

	public void setAddFriendDialog(JDialog addFriendDialog) {
		this.addFriendDialog = addFriendDialog;
	}

	public JTextField getTxtIPAddress() {
		if (txtIPAddress == null) {
			txtIPAddress = new JTextField();
		}
		return txtIPAddress;
	}

	public JTextField getTxtPort() {
		if (txtPort == null) {
			txtPort = new JTextField();
		}
		return txtPort;
	}

	public JTextField getTxtName() {
		if (txtName == null) {
			txtName = new JTextField();
		}
		return txtName;
	}

	public JPanel getDialogPanel() {
		if (dialogPanel == null) {
			dialogPanel = new JPanel(new GridLayout(4, 3));
		}
		return dialogPanel;
	}

	public JPopupMenu getPopupMenu() {
		if (popupMenu == null) {
			popupMenu = new JPopupMenu();
			JMenuItem editItem = new JMenuItem("Edit");
			JMenuItem deleteItem = new JMenuItem("Delete");
			JMenuItem chatGroupItem = new JMenuItem("Chat group");

			// edit action
			editItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					int index = list.getSelectedIndex();
					if (index >= 0 && index < listModel.size()) {
						PersonInfo selectedPerson = friendList.get(index);

						String newName = (String) JOptionPane.showInputDialog(
								frmPpMessenger, "Please enter the new name",
								"Edit", JOptionPane.PLAIN_MESSAGE, null, null,
								selectedPerson.getName());

						try {
							if (newName == null
									|| newName.equals(selectedPerson.getName())) {
								return;
							} else if (newName.isEmpty()) {
								JOptionPane
										.showMessageDialog(
												frmPpMessenger,
												"Can not change name. The name couldn't empty",
												"Error",
												JOptionPane.ERROR_MESSAGE);
							} else if (Util.isNameExist(newName, friendList)) {
								JOptionPane
										.showMessageDialog(
												frmPpMessenger,
												"This name is exist in your friend list",
												"Error",
												JOptionPane.ERROR_MESSAGE);
							} else {
								selectedPerson.setName(newName);
								friendList.set(index, selectedPerson);
								Util.saveToFile(Util.filePath, friendList);
								updateListModel();
							}
						} catch (Exception e2) {
							e2.printStackTrace();
							JOptionPane.showMessageDialog(frmPpMessenger,
									"Can not save friends list to file.",
									"Error", JOptionPane.ERROR_MESSAGE);
						}

					}

				}
			});

			// delete action
			deleteItem.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					int index = list.getSelectedIndex();
					if (index >= 0 && index < listModel.size()) {
						int result = JOptionPane.showConfirmDialog(
								frmPpMessenger,
								"Do you want to remove this friend?",
								"Remove friend", JOptionPane.YES_NO_OPTION);

						try {
							if (result == 0) {
								friendList.remove(index);
								Util.saveToFile(Util.filePath, friendList);
								listModel.remove(index);
							}
						} catch (Exception e2) {
							e2.printStackTrace();
							JOptionPane.showMessageDialog(frmPpMessenger,
									"Can not update friends list to file.",
									"Error", JOptionPane.ERROR_MESSAGE);
						}

					}
				}
			});

			// Chat group
			chatGroupItem.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					GroupChatFrame groupChatFrame = new GroupChatFrame();
					groupChatFrame.setVisible(true);
					groupChatFrame.addElementToListModel(friendList.get(list
							.getSelectedIndex()));

					groupChatFrame.getContentPane().add(groupChatFrame);
				}
			});

			popupMenu.add(editItem);
			popupMenu.add(deleteItem);
		}

		return popupMenu;
	}

	private Component getGlue() {
		if (glue == null) {
			glue = Box.createGlue();
		}
		return glue;
	}

	private JButton getBtnSetting() {
		if (btnSetting == null) {
			btnSetting = new JButton("Setting");
			btnSetting.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					int temp = 0;
					do {
						String strPort = (String) JOptionPane.showInputDialog(
								frmPpMessenger, "Change the port number: ",
								"Setting", JOptionPane.QUESTION_MESSAGE, null,
								null, myInfo.getPort().toString());
						try {
							if (strPort != null) {
								myInfo.setPort(Integer.parseInt(strPort));
							}
							// Stop listener
							isListen = false;
							TimeUnit.MILLISECONDS.sleep(500);
							isListen = true;
							temp = 1;
						} catch (Exception e) {
							JOptionPane.showMessageDialog(frmPpMessenger,
									"Please enter the valid port number");
						}
					} while (temp == 0);
				}
			});
		}
		return btnSetting;
	}

	private JButton getBtnGroupChat() {
		if (btnGroupChat == null) {
			btnGroupChat = new JButton("Chat group");
			btnGroupChat.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					final FriendsList_DlgAdd friendsList_DlgAdd = new FriendsList_DlgAdd() {

						@Override
						protected void sendData(JTable table) {
							int[] rowIds = table.getSelectedRows();
							if (rowIds.length <= 0) {
								JOptionPane.showMessageDialog(table,
										"Please select one friend at least");
							} else {
								try {
									Long idChatRoom = new Random(System
											.currentTimeMillis()).nextLong();

									List<PersonInfo> invitedList = new ArrayList<>();
									for (int i : rowIds) {
										invitedList.add(T2Messenger.friendList
												.get(i));
									}

									invitedList.add(T2Messenger.myInfo);

									for (int i : rowIds) {
										UDPUtil.sendMessage(
												Util.convertToByteArray(invitedList),
												T2Messenger.friendList.get(i),
												Packet.TYPE_GROUP_CHAT_REQ,
												Packet.FLAG_DATA,
												ByteBuffer
														.allocate(
																Packet.OPTION_DATA_LENGTH)
														.putLong(idChatRoom)
														.array());
									}

									GroupChatFrame groupChatFrame = new GroupChatFrame();
									groupChatFrame
											.setChatGroupNumber(idChatRoom);
									groupChatFrame.setVisible(true);
									groupChatFrames.add(groupChatFrame);
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					};
					friendsList_DlgAdd.setVisible(true);
				}
			});
		}
		return btnGroupChat;
	}
}
